package com.ddpt.permission.service.login;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lh.center.common.constant.GlobalConstant;
import com.lh.center.common.constant.RedisPrefix;
import com.lh.center.common.dto.LoginByPhoneDto;
import com.lh.center.common.exception.CommonException;
import com.lh.center.common.exception.ErrorEnum;
import com.lh.center.common.util.AssertUtil;
import com.lh.center.common.web.session.SessionOperation;
import com.lh.center.permission.api.entity.StoreAdminUser;
import com.lh.center.permission.api.session.StoreSessionUser;
import com.lh.center.permission.service.LoginService;
import com.lh.center.permission.service.StoreAdminUserService;
import com.lh.center.permission.util.ImageCodeUtil;
import com.lh.center.reach.api.dubbo.DubboExternalMerchantConfigService;
import com.lh.center.reach.api.entity.ExternalMerchantConfigEntity;
import com.lh.center.store.api.dubbo.DubboStoreService;
import com.lh.center.store.api.entity.StoreBusinessEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service("storeLoginService")
public class StoreLoginServiceImpl implements LoginService<StoreSessionUser> {

    @Value("${admin.timeout.store:30}")
    private Integer loginTimeout;

    @Autowired
    private ImageCodeUtil imageCodeUtil;

    @Autowired
    private StoreAdminUserService storeAdminUserService;

    @DubboReference
    private DubboStoreService dubboStoreService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @DubboReference
    private DubboExternalMerchantConfigService dubboExternalMerchantConfigService;

    @Override
    public StoreSessionUser loginByPassword(String account, String password, String imgCode, String codeId) {
        imageCodeUtil.verifyCode(codeId, imgCode);
        return loginByPassword(account, password);
    }

    @Override
    public StoreSessionUser loginByPassword(String account, String password) {
        LambdaQueryWrapper<StoreAdminUser> wrapper = Wrappers.lambdaQuery(StoreAdminUser.class);
        wrapper.eq(StoreAdminUser::getUserName, account);
        wrapper.eq(StoreAdminUser::getPassword, DigestUtil.md5Hex(password));
        wrapper.eq(StoreAdminUser::getDeleted, GlobalConstant.ZERO);
        StoreAdminUser adminUser = storeAdminUserService.getOne(wrapper);
        if (null == adminUser) {
            throw new CommonException(ErrorEnum.USERNAME_OR_PASSWORD_ERROR);
        } else if (GlobalConstant.ZERO.equals(adminUser.getStatus())) {
            throw new CommonException(ErrorEnum.ADMIN_INVALID);
        }
        return loginSuccess(adminUser);
    }

    @Override
    public StoreSessionUser autoLogin(Long merchantId, String phone, String randomSecret) {
        StoreAdminUser user = storeAdminUserService.get(Wrappers.lambdaQuery(StoreAdminUser.class)
                .eq(StoreAdminUser::getUserName, phone)
                .eq(StoreAdminUser::getMerchantId, merchantId)
        );
        AssertUtil.isNull(user, "自动登陆失败，用户不存在");
        if (StringUtils.isNotBlank(user.getRandomSecret()) && !user.getRandomSecret().equals(randomSecret)) {
            throw new CommonException("自动登陆失败,随机码错误");
        }
        user.setRandomSecret(UUID.randomUUID().toString().replace("-", ""));
        storeAdminUserService.updateById(user);
        return loginSuccess(user);
    }

    private StoreSessionUser loginSuccess(StoreAdminUser adminUser) {
        StoreSessionUser sessionUser = new StoreSessionUser();
        sessionUser.setInsId(adminUser.getInsId());
        sessionUser.setUserId(adminUser.getId());
        sessionUser.setMerchantId(adminUser.getMerchantId());
        StoreBusinessEntity storeBusinessEntity = dubboStoreService.getByStoreUserId(adminUser.getId());
        log.info("商家登录查出商家信息:{}",JSONUtil.toJsonStr(storeBusinessEntity));
        Assert.notNull(storeBusinessEntity, "商家不存在");
        sessionUser.setStoreId(storeBusinessEntity.getId());
        sessionUser.setUserName(adminUser.getUserName());
        sessionUser.setAccount(adminUser.getUserName());
        sessionUser.setStatus(adminUser.getStatus());
        String token = UUID.randomUUID().toString();
        //是否开启加解密
        if (SessionOperation.getConfiguration().isEnableSecret()) {
            sessionUser.setSecret(RandomUtil.randomString(16));
            sessionUser.setSecretEnabled(true);
        }
        sessionUser.setToken(token);
        Long configId = storeBusinessEntity.getConfigId();
        sessionUser.setConfigId(storeBusinessEntity.getConfigId());
        if (Objects.nonNull(configId)) {
            ExternalMerchantConfigEntity merchantConfigEntity = dubboExternalMerchantConfigService.getById(configId);
            if (Objects.nonNull(merchantConfigEntity)) {
                sessionUser.setConfigInfo(new JSONObject(merchantConfigEntity));
            }
        }

        sessionUser.setGoodsCheck(storeBusinessEntity.getGoodsCheck());

        redisTemplate.opsForValue().set(RedisPrefix.STORE_ADMIN_USER_TOKEN + token, JSONUtil.toJsonStr(sessionUser), loginTimeout, TimeUnit.MINUTES);
        return sessionUser;
    }

    public StoreSessionUser loginByPasswordCallBack(String account, String password) {
        LambdaQueryWrapper<StoreAdminUser> wrapper = Wrappers.lambdaQuery(StoreAdminUser.class);
        wrapper.eq(StoreAdminUser::getUserName, account);
        wrapper.eq(StoreAdminUser::getPassword, password);
        wrapper.eq(StoreAdminUser::getDeleted, GlobalConstant.ZERO);
        StoreAdminUser adminUser = storeAdminUserService.getOne(wrapper);
        if (null == adminUser) {
            throw new CommonException(ErrorEnum.USERNAME_OR_PASSWORD_ERROR);
        } else if (GlobalConstant.ZERO.equals(adminUser.getStatus())) {
            throw new CommonException(ErrorEnum.ADMIN_INVALID);
        }
        StoreSessionUser sessionUser = new StoreSessionUser();
        sessionUser.setInsId(adminUser.getInsId());
        sessionUser.setUserId(adminUser.getId());
        sessionUser.setMerchantId(adminUser.getMerchantId());
        sessionUser.setStoreId(adminUser.getId());
        sessionUser.setUserName(account);
        sessionUser.setAccount(account);
        sessionUser.setStatus(adminUser.getStatus());
        String token = UUID.randomUUID().toString();
        sessionUser.setSecret(RandomUtil.randomString(16));
        sessionUser.setToken(token);
        redisTemplate.opsForValue().set(RedisPrefix.STORE_ADMIN_USER_TOKEN + token, JSONUtil.toJsonStr(sessionUser), loginTimeout, TimeUnit.MINUTES);
        return sessionUser;
    }

    @Override
    public StoreSessionUser loginByPhone(LoginByPhoneDto dto) {
        return null;
    }

    @Override
    public void signOut(String token) {

    }
}
